#include "ValMgr.h"
#include "Globe.h"
ValMgr::ValMgr(VMTYPE mode, ValMgr* father_block)
{
    this->_reserve = 0;
    this->_offset = 0;
    this->_mode = mode;
    this->_father_block = father_block;
    if(this->_mode==BLOCK)
    {
        if (this->_father_block == nullptr)
            return;
        this->_offset = this->_father_block->_offset + this->_father_block->_reserve;
    }
}

ValMgr* ValMgr::GetFatherBlockValMgr()
{
    return this->_father_block;
}

bool ValMgr::Alloc(string str, bool editable)
{
    this->_reserve += 4;
    if (this->_val_logs.count(str))return false;
    ValLog valLog;
    valLog.editable = editable;
    valLog.length = 4;
    valLog.offset = this->_reserve;
    this->_val_logs[str] = valLog;
    if (this->_mode == BLOCK)
        this->_father_block->Update(this->_offset + this->_reserve);
    return true;
}

void ValMgr::Update(int n)
{
    if (this->_reserve < n)
    {
        this->_reserve = n;
        if (this->_mode == BLOCK)
            this->_father_block->Update(this->_offset + this->_reserve);
    }
}

bool ValMgr::Lookup(string str)
{
    if (this->_val_logs.count(str))return true;
    if (this->_father_block == nullptr)return false;
    return this->_father_block->Lookup(str);
}

ValLog ValMgr::QueryVal(string str)
{
    if (this->_val_logs.count(str))return this->_val_logs.find(str)->second;
    if (this->_father_block == nullptr)return ValLog();
    return this->_father_block->QueryVal(str);
}

int ValMgr::QueryOffset(string str)
{
    if (this->_val_logs.count(str))return -this->_val_logs.find(str)->second.offset;
    if (this->_father_block == nullptr)return 0;
    return this->_father_block->QueryOffset(str);
}

int ValMgr::QueryOffsetRegister(string str)
{
    if (this->_val_logs.count(str))
        if (this->_mode == GLOBAL)return EIP;
        else return EBP;
    if (this->_father_block == nullptr)return 0;
    return this->_father_block->QueryOffsetRegister(str);
}

bool ValMgr::QueryEditability(string str)
{
    if (this->_val_logs.count(str))return this->_val_logs.find(str)->second.editable;
    if (this->_father_block == nullptr)return 0;
    return this->_father_block->QueryOffset(str);
}
